package com.haohuo.filter;

import com.alibaba.fastjson.JSON;
import com.haohuo.config.constans.TraceConstans;
import com.haohuo.filter.model.TraceResponse;
import com.haohuo.util.DateTimeTraceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.web.util.ContentCachingResponseWrapper;
import org.springframework.web.util.WebUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

/**
 * @Author: pk.zhang
 * @Date: 2021/3/3 16:57
 */
public class TraceFilter implements Filter {



    private static final Logger log = LoggerFactory.getLogger(TraceFilter.class);


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }


    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        // 通过包装对象打印请求信息
        try {
            HttpServletRequest request = (HttpServletRequest) req;
            MutableHttpServletRequest requestWrapper = new MutableHttpServletRequest(request);

            HttpServletResponse response = (HttpServletResponse) res;
            ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);

            chain.doFilter(requestWrapper, responseWrapper);

            // 打印响应信息
            TraceResponse traceResponse = new TraceResponse();
            traceResponse.setTraceID(request.getHeader(TraceConstans.TRACEID_KEY));
            HttpHeaders headers = new HttpHeaders();
            if (response.getHeaderNames() != null) {
                for (String headerName : response.getHeaderNames()) {
                    headers.add(headerName, response.getHeader(headerName));
                }
            }
            traceResponse.setHeaders(headers);
            traceResponse.setStatusCode(HttpStatus.resolve(response.getStatus()));
            traceResponse.setStartTime(DateTimeTraceUtil.getNowDateTime());
            traceResponse.setRespJson(getResponseBody(responseWrapper));
            log.info("trace response:{}", JSON.toJSONString(traceResponse));

            // 重写到response
            responseWrapper.copyBodyToResponse();
        } finally {
            MDC.clear();
        }
    }

    /**
     * 打印请求参数
     * @param response
     */
    private String getResponseBody(ContentCachingResponseWrapper response) {
        ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
        if(wrapper != null) {
            byte[] buf = wrapper.getContentAsByteArray();
            if(buf.length > 0) {
                String payload;
                try {
                    payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding());
                } catch (UnsupportedEncodingException e) {
                    payload = "[unknown]";
                }
                return payload;
            }
        }
        return "";
    }






    @Override
    public void destroy() {

    }
}
